package generator;
// Based on project found at: https://github.com/Clairette/sudoku/

import java.util.Random;

public class Generator
{
	private Board board = new Board();
	private Board srcBoard = new Board(); // srcBoard is a board to backtrack to if something goes wrong
	
	public Generator() { }
	
	public Board getBoard()
	{
		return this.board;
	}
	
	public void generateBoard(int diff)
	{
		initBoard();
		Random random = new Random();
		// easy
		if (diff == 1)
		{
			dig(30 + random.nextInt(10));
		}
		// medium
		else if (diff == 2)
		{
			dig(40 + random.nextInt(10));
		}
		// hard
		else
		{
			dig(50 + random.nextInt(10));
		}
	}
	
	private void initBoard()
	{
		int col, row, number;
		
		do
		{
			board.clear();
			for (int k = 0; k < 80; k++)
			{
				col = random();
				row = random();
				number = random() + 1;
				
				if (!board.contains(col, row, number))
				{
					board.setCell(col, row, number, true);
				}
			}
		}
		while (!solvable());
		
		srcBoard.copy(board);
	}
	
	private int random()
	{
		Random rand = new Random();
		return rand.nextInt(9);
	}
	
	private boolean solvable()
	{
		Solver solver = new Solver(board, true);
		return solver.solveBoard();
	}
	
	private boolean multSol()
	{
		int n = 0;
		for (int col = 0; col < 9; col++)
		{
			for (int row = 0; row < 9; row++)
			{
				if (srcBoard.getCell(col, row) != null && srcBoard.getCell(col, row).equals(0))
				{
					// if a cell in the original puzzle is empty
					for (int num = 1; num < 10; num++)
					{
						// loop through all possible numbers for this cell
						board.copy(srcBoard);
						board.setCell(col, row, num, true);
						if (!board.contains(col, row, num) && solvable())
						{
							// count all possible solutions for numbers in this cell
							n++;
						}
					}
					
					if (n > 1)
					{
						// if there is more than one possible solution, return true
						return true;
					}
					board.setCell(col, row, 0, false);
				}
			}
		}
		// if after testing all possible numbers for all empty cells there is not more than one solution, return false
		return false;
	}
	
	private void dig(int n)
	{
		int col, row, num, dug = 0;
		while (dug < n)
		{
			col = random();
			row = random();
			if (board.getCell(col, row) == null || !board.getCell(col, row).equals(0))
			{
				if (board.getCell(col, row) == null)
				{
					num = 0;
				}
				else
				{
					num = board.getCell(col, row).getNumber();
				}
				board.setCell(col, row, 0, false);
				if (!multSol())
				{
					dug++;
				}
				else
				{
					board.setCell(col, row, num, true);
				}
			}
		}
	}
}